unit ec_setvariables;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, Buttons,
  StdCtrls, EditBtn, Spin, ec_base, fpjson;

type

  { TECSetVariablesFrame }

  TECSetVariablesFrame = class(TECBaseFrame)
    ScriptEdit: TEdit;
    GameDataEditButton: TEditButton;
    GameDataRadioButton: TRadioButton;
    ScriptRadioButton: TRadioButton;
    RandomToSpinEdit: TSpinEdit;
    RandomToLabel: TLabel;
    RandomFromLabel: TLabel;
    RandomOperandRadioButton: TRadioButton;
    RandomFromSpinEdit: TSpinEdit;
    VariableOperandEditButton: TEditButton;
    OperandGroupBox: TGroupBox;
    OperatorRadioGroup: TRadioGroup;
    ConstantOperandRadioButton: TRadioButton;
    VariableOperandRadioButton: TRadioButton;
    SingleVarEditButton: TEditButton;
    SingleVarRadioButton: TRadioButton;
    ConstantOperandSpinEdit: TSpinEdit;
    VarRangeFromLabel: TLabel;
    VarRangeFromSpinEdit: TSpinEdit;
    VarRangeRadioButton: TRadioButton;
    VarRangeToLabel: TLabel;
    VarRangeToSpinEdit: TSpinEdit;
    VarToSetGroupBox: TGroupBox;
    procedure AnyRadioButtonChanged(Sender: TObject);
    procedure GameDataEditButtonButtonClick(Sender: TObject);
    procedure GameDataEditButtonKeyPress(Sender: TObject; var Key: char);
    procedure SingleVarEditButtonButtonClick(Sender: TObject);
    procedure SingleVarEditButtonKeyPress(Sender: TObject; var Key: char);
    procedure VariableOperandEditButtonButtonClick(Sender: TObject);
    procedure VariableOperandEditButtonKeyPress(Sender: TObject; var Key: char);
  private
    SingleVarId, VariableOperandId: Integer;
    GameDataArgs: TJSONArray;
    procedure ToggleEnabledState;
    procedure UpdateVarNames;
    procedure UpdateGameDataArg;
    procedure InitialSetup;
    function GetSelectedOperandType: Integer;
  public
    procedure InitNew; override;
    procedure InitExisting; override;
    procedure MakeResultingCommand; override;

    destructor Destroy; override;
  end;

var
  ECSetVariablesFrame: TECSetVariablesFrame;

const
  SET_VAR_OPERAND_CONSTANT = 0;
  SET_VAR_OPERAND_VAR = 1;
  SET_VAR_OPERAND_RANDOM = 2;
  SET_VAR_OPERAND_GAMEDATA = 3;
  SET_VAR_OPERAND_SCRIPT = 4;

implementation

{$R *.lfm}

uses
  constants, namedindexselection, namehelper, gamedataformunit;

{ TECSetVariablesFrame }

procedure TECSetVariablesFrame.AnyRadioButtonChanged(Sender: TObject);
begin
  ToggleEnabledState
end;

procedure TECSetVariablesFrame.GameDataEditButtonButtonClick(Sender: TObject);
var
  F: TGameDataForm;
begin
  F := TGameDataForm.Create(Self);
  if F.SelectGameData(Db, Troop, GameDataArgs) then begin
    FreeAndNil(GameDataArgs);
    GameDataArgs := F.GetArgs;
  end;
  F.Free;

  UpdateGameDataArg;
end;

procedure TECSetVariablesFrame.GameDataEditButtonKeyPress(Sender: TObject;
  var Key: char);
begin
  Key := #0;
  GameDataEditButtonButtonClick(Sender)
end;

procedure TECSetVariablesFrame.SingleVarEditButtonButtonClick(Sender: TObject);
begin
  SingleVarId := NamedIndexSelectionForm.SelectVariable(SingleVarId, Db);
  UpdateVarNames
end;

procedure TECSetVariablesFrame.SingleVarEditButtonKeyPress(Sender: TObject;
  var Key: char);
begin
  Key := #0;
  SingleVarEditButtonButtonClick(Sender)
end;

procedure TECSetVariablesFrame.VariableOperandEditButtonButtonClick(
  Sender: TObject);
begin
  VariableOperandId := NamedIndexSelectionForm.SelectVariable(VariableOperandId, Db);
  UpdateVarNames
end;

procedure TECSetVariablesFrame.VariableOperandEditButtonKeyPress(
  Sender: TObject; var Key: char);
begin
  Key := #0;
  VariableOperandEditButtonButtonClick(Sender)
end;

procedure TECSetVariablesFrame.ToggleEnabledState;
begin
  SingleVarEditButton.Enabled := SingleVarRadioButton.Checked;
  VarRangeFromSpinEdit.Enabled := VarRangeRadioButton.Checked;
  VarRangeToSpinEdit.Enabled := VarRangeRadioButton.Checked;

  ConstantOperandSpinEdit.Enabled := ConstantOperandRadioButton.Checked;
  VariableOperandEditButton.Enabled := VariableOperandRadioButton.Checked;
  RandomFromSpinEdit.Enabled := RandomOperandRadioButton.Checked;
  RandomToSpinEdit.Enabled := RandomOperandRadioButton.Checked;
  GameDataEditButton.Enabled := GameDataRadioButton.Checked;
  ScriptEdit.Enabled := ScriptRadioButton.Checked
end;

procedure TECSetVariablesFrame.UpdateVarNames;
begin
  SingleVarEditButton.Text := Db.GetVariableName(SingleVarId);
  VariableOperandEditButton.Text := Db.GetVariableName(VariableOperandId);
end;

procedure TECSetVariablesFrame.UpdateGameDataArg;
begin
  if GameDataArgs <> nil then
    GameDataEditButton.Text := SetVar_GetGameData(GameDataArgs, Db, 0)
  else
    GameDataEditButton.Text := '';
end;

procedure TECSetVariablesFrame.InitialSetup;
begin
  with OperatorRadioGroup.Items do begin
    BeginUpdate;
    Clear;
    Add(rsSetVariables_setSingleItem); 
    Add(rsSetVariables_addSingleItem);
    Add(rsSetVariables_subSingleItem);
    Add(rsSetVariables_mulSingleItem);
    Add(rsSetVariables_divSingleItem);
    Add(rsSetVariables_modSingleItem);
    EndUpdate;
  end;

  if SingleVarId < 1 then
    SingleVarId := 1;
  if VariableOperandId < 1 then
    VariableOperandId := 1;
end;

function TECSetVariablesFrame.GetSelectedOperandType: Integer;
begin
  if ConstantOperandRadioButton.Checked then
    Result := SET_VAR_OPERAND_CONSTANT
  else if VariableOperandRadioButton.Checked then
    Result := SET_VAR_OPERAND_VAR
  else if RandomOperandRadioButton.Checked then
    Result := SET_VAR_OPERAND_RANDOM
  else if GameDataRadioButton.Checked then
    Result := SET_VAR_OPERAND_GAMEDATA
  else
    Result := SET_VAR_OPERAND_SCRIPT
end;

procedure TECSetVariablesFrame.InitNew;
begin
  InitialSetup;

  SingleVarRadioButton.Checked := True;
  SingleVarId := 1;
  VariableOperandId := 1;
  UpdateVarNames;
  OperatorRadioGroup.ItemIndex := 0;
  ConstantOperandRadioButton.Checked := True;

  GameDataArgs := TJSONArray.Create([gdtItem, 1]);
  UpdateGameDataArg;

  ToggleEnabledState
end;

procedure TECSetVariablesFrame.InitExisting;
var
  Params: TJSONArray;

  procedure InitVariable;
  var
    StartId, EndId: Integer;
  begin
    if (Params.Count >= 1) and (Params[0].JSONType = jtNumber) then
     StartId := Params.Integers[0];

    if (Params.Count >= 2) and (Params[1].JSONType = jtNumber) then
     EndId := Params.Integers[1];

    SingleVarId := StartId;
    UpdateVarNames;
    VarRangeFromSpinEdit.Value := StartId;
    VarRangeToSpinEdit.Value := EndId;

    if StartId = EndId then begin
      VarRangeRadioButton.Checked := False;
      SingleVarRadioButton.Checked := True;
    end else begin
      SingleVarRadioButton.Checked := False;
      VarRangeRadioButton.Checked := True;
    end;
  end;

  procedure InitOperator;
  begin
    if (Params.Count >= 3) and (Params[2].JSONType = jtNumber) then
      OperatorRadioGroup.ItemIndex := Params.Integers[2];
  end;

  procedure InitOperand;
  var
    OperandType: Integer = 0;

    procedure InitConstant;
    begin
      ConstantOperandRadioButton.Checked := True;
      if (Params.Count >= 5) and (Params[4].JSONType = jtNumber) then
        ConstantOperandSpinEdit.Value := Params.Integers[4];
    end;

    procedure InitVar;
    begin
      VariableOperandRadioButton.Checked := True;
      if (Params.Count >= 5) and (Params[4].JSONType = jtNumber) then
        VariableOperandId := Params.Integers[4]
      else
        VariableOperandId := 1;
      UpdateVarNames
    end;

    procedure InitRandom;
    begin
      RandomOperandRadioButton.Checked := True;
      if (Params.Count >= 5) and (Params[4].JSONType = jtNumber) then
        RandomFromSpinEdit.Value := Params.Integers[4];
      if (Params.Count >= 6) and (Params[5].JSONType = jtNumber) then
        RandomToSpinEdit.Value := Params.Integers[5];
    end;

    procedure InitGameData;
    var
      I: Integer;
    begin
      GameDataRadioButton.Checked := True;

      if GameDataArgs <> nil then
        FreeAndNil(GameDataArgs);

      GameDataArgs := TJSONArray.Create;
      for I := 4 to Params.Count -1 do begin
          GameDataArgs.Add(Params[I].Clone);
      end;

      UpdateGameDataArg
    end;

    procedure InitScript;
    begin
      ScriptRadioButton.Checked := True;
      if (Params.Count >= 5) and (Params[4].JSONType = jtString) then
        ScriptEdit.Text := Params.Strings[4];
    end;

  begin
    {TODO}
    if (Params.Count >= 4) and (Params[3].JSONType = jtNumber) then
      OperandType := Params.Integers[3];

    case OperandType of
      SET_VAR_OPERAND_CONSTANT: InitConstant;
      SET_VAR_OPERAND_VAR: InitVar;
      SET_VAR_OPERAND_RANDOM: InitRandom;
      SET_VAR_OPERAND_GAMEDATA: InitGameData;
      SET_VAR_OPERAND_SCRIPT: InitScript;
    end;
  end;

begin
  Params := GetFirstParams;

  InitialSetup;
  InitVariable;
  InitOperator;
  InitOperand;

  if GameDataArgs = nil then begin
    GameDataArgs := TJSONArray.Create([gdtItem, 1]);
    UpdateGameDataArg
  end;

  ToggleEnabledState;

  inherited InitExisting; {TODO}
end;

procedure TECSetVariablesFrame.MakeResultingCommand;
var
  StartId, EndId: Integer;
  VarCmdParams: TJSONArray;

  procedure FillStartEndIds;
  begin
    if SingleVarRadioButton.Checked then begin
      StartId := SingleVarId;
      EndId := SingleVarId
    end else begin
      StartId := VarRangeFromSpinEdit.Value;
      EndId := VarRangeToSpinEdit.Value
    end;
  end;

  procedure AddOperandParams;
    procedure AddConstantParams;
    begin
      VarCmdParams.Add(SET_VAR_OPERAND_CONSTANT);
      VarCmdParams.Add(ConstantOperandSpinEdit.Value);
    end;

    procedure AddVarParams;
    begin
      VarCmdParams.Add(SET_VAR_OPERAND_VAR);
      VarCmdParams.Add(VariableOperandId);
    end;

    procedure AddRandomParams;
    begin
      VarCmdParams.Add(SET_VAR_OPERAND_RANDOM);
      VarCmdParams.Add(RandomFromSpinEdit.Value);
      VarCmdParams.Add(RandomToSpinEdit.Value);
    end;

    procedure AddGameDataParams;
    var
      I: Integer;
    begin
      VarCmdParams.Add(SET_VAR_OPERAND_GAMEDATA);
      if GameDataArgs <> nil then
        for I := 0 to GameDataArgs.Count -1 do
            VarCmdParams.Add(GameDataArgs[I].Clone);
    end;

    procedure AddScriptParams;
    begin
      VarCmdParams.Add(SET_VAR_OPERAND_SCRIPT);
      VarCmdParams.Add(ScriptEdit.Text);
    end;

  begin
    if ConstantOperandRadioButton.Checked then
      AddConstantParams
    else if VariableOperandRadioButton.Checked then
      AddVarParams
    else if RandomOperandRadioButton.Checked then
      AddRandomParams
    else if GameDataRadioButton.Checked then
      AddGameDataParams
    else if ScriptRadioButton.Checked then
      AddScriptParams;
  end;

begin
  FillStartEndIds;

  VarCmdParams := TJSONArray.Create([
    StartId, EndId, OperatorRadioGroup.ItemIndex
  ]);
  AddOperandParams;

  ResultingCommand := TJSONArray.Create([
    TJSONObject.Create([
      'code', SET_VARIABLES_EC_CODE,
      'indent', Indent,
      'parameters', VarCmdParams
    ])
  ]);
end;

destructor TECSetVariablesFrame.Destroy;
begin
  if GameDataArgs <> nil then
    FreeAndNil(GameDataArgs);

  inherited Destroy;
end;

end.

